package presencial2011;

import java.util.ArrayList;
import java.util.InputMismatchException;
import java.util.Scanner;

/**
 * 
 * @author Hijos de Object
 * 
 */
public class CodigoDeBarras {
	/**
	 * atributo scan atributo ArrayList para guardar n numeros. Es String porque
	 * si los guardo en un int, el codigo de barras de 13 caracteres no cabe.
	 */
	private Scanner scan = new Scanner(System.in);
	private ArrayList<String> coleccionCodigoBarras = new ArrayList<String>();
	private int digitoControl;
	private int digitoControlAValidar;

	/**
	 * Constructor por defecto
	 */
	public CodigoDeBarras() {

		coleccionarCodigos();
		mostrarSolucion();

	}

	private void mostrarSolucion() {
		// El iterado reccorre la coleccion para mostrar los numeros
		// introducidos.
		try {

			for (String codigos : coleccionCodigoBarras) {
				calcularCodigos(codigos);
				if (this.digitoControl == this.digitoControlAValidar) {
					System.out.print("Si ");
					if (codigos.length() == 13
							|| (codigos.length() > 8 && codigos.length() < 13)) {
						System.out.print(estableceCodigoPais(codigos));
					}
					System.out.println();
				} else {
					System.out.println("No");
				}

			}
		} catch (NumberFormatException e) {
			System.out.println("Error!! Introduce datos numericos...");
		}

	}

	/**
	 * Calcula el digito de comprobacion de cada codigo de barras
	 * 
	 * @param codigoBarras
	 */
	private void calcularCodigos(String codigoBarras)
			throws NumberFormatException {
		int accImpares = 0;
		int accPares = 0;
		// Se guarda en una variable la cadena codigoBarras menos el ultimo
		// digito
		String codigoaux = codigoBarras.substring(0, codigoBarras.length() - 1);

		/*
		 * Me guardo en el atributo, el ultimo caracter de la cadena
		 * codigoBarras, el cual sera el DigitoControl a validar mas adelante.
		 */

		String digitoComprobAuxiliar = codigoBarras.substring(
				codigoBarras.length() - 1, codigoBarras.length());
		// Lo transformo a entero.
		this.digitoControlAValidar = Integer.parseInt(digitoComprobAuxiliar);

		// bucle que diferencia entre posicion IMPAR
		for (int i = codigoaux.length() - 1; i >= 0; i = i - 2) {
			accImpares = accImpares + ((codigoaux.charAt(i) - 48) * 3);
		}
		// bucle que diferencia entre posicion PAR
		for (int i = codigoaux.length() - 2; i >= 0; i = i - 2) {

			accPares = accPares + (codigoBarras.charAt(i) - 48);
			// 48 es el valor 0 del codigo ASCII (asi paso de char a
			// int)

		}
		int digitoComprobacion = accPares + accImpares;
		calculaDigitoControl(digitoComprobacion);
	}

	/**
	 * Calcula el digito de control para despues compararlo con el atributo
	 * supuestoDigitoControl. Si son iguales; el codigo de barras EAN-8 es
	 * valido.
	 * 
	 * @param digitoComprobacion
	 */
	private void calculaDigitoControl(int digitoComprobacion) {

		int aComprobar = digitoComprobacion;
		this.digitoControl = 0;
		if (esMultiploDiez(digitoComprobacion)) {
			this.digitoControl = 0;
		} else {
			while (esMultiploDiez(aComprobar) == false) {
				this.digitoControl++;
				aComprobar++;

			}
		}

	}

	/**
	 * Averigua si digitoControl es multiplo de 10
	 * 
	 * @param digitoControl
	 * @return true si es multiplo de 10
	 */
	private boolean esMultiploDiez(int numero) {
		if (numero % 10 == 0) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * coleccionar codigos: pide por teclado codigo de barras y los agrega al
	 * arrayList. Finaliza cuando se introduce el 0
	 */
	private void coleccionarCodigos() {
		String nIntroducido;
		try {
			System.out.println("Introduce n...");
			nIntroducido = scan.next();

			while (!(nIntroducido.equals("0"))) {

				String validado = validarLongitudCodigo(nIntroducido);
				coleccionCodigoBarras.add(validado);
				System.out.println("Introduce n...");
				nIntroducido = scan.next();

			}
		} catch (NumeroLargoException e) {
			System.out.println(e.toString());
		} catch (InputMismatchException e) {
			System.out.println("Error. Introduce un dato numerico");
		}

	}

	/**
	 * Comprueba que el numero introducido es correcto.
	 * 
	 * @param nIntroducido
	 * @return String validado
	 * @throws NumeroLargoException
	 *             cuando el numero supera los valores especificados
	 */
	private String validarLongitudCodigo(String nIntroducido)
			throws NumeroLargoException {
		String numAValidar = nIntroducido;
		String numCeros = "";
		String sol = "";
		if (numAValidar.length() < 8) {
			for (int i = 0; i < (8 - numAValidar.length()); i++) {
				numCeros = numCeros + "0";
			}
			sol = numCeros + numAValidar;
		} else if (numAValidar.length() > 8 && numAValidar.length() < 13) {
			for (int i = 0; i < (13 - numAValidar.length()); i++) {
				numCeros = numCeros + "0";
			}
			sol = numCeros + numAValidar;
		} else if (numAValidar.length() == 13) {
			sol = numAValidar;
		} else if (numAValidar.length() == 8) {
			sol = numAValidar;
		} else if (numAValidar.length() > 13) {
			throw (new NumeroLargoException());
		}
		return sol;
	}

	private String estableceCodigoPais(String sol) {
		String devolverCodigo = "";
		String[] arrayCodigosPais = { "EEUU", "Bulgaria", "Inglaterra",
				"Irlanda", "Portugal", "Noruega", "Venezuela", "Cuba", "India" };
		switch (sol.charAt(0)) {

		case '0':
			devolverCodigo = arrayCodigosPais[0];
			break;
		}
		if (sol.substring(0, 3).equals("380")) {
			devolverCodigo = arrayCodigosPais[1];
		} else if (sol.substring(0, 2).equals("50")) {
			devolverCodigo = arrayCodigosPais[2];

		} else if (sol.substring(0, 3).equals("539")) {
			devolverCodigo = arrayCodigosPais[3];

		} else if (sol.substring(0, 3).equals("560")) {
			devolverCodigo = arrayCodigosPais[4];

		} else if (sol.substring(0, 2).equals("70")) {
			devolverCodigo = arrayCodigosPais[5];

		} else if (sol.substring(0, 3).equals("759")) {
			devolverCodigo = arrayCodigosPais[6];

		} else if (sol.substring(0, 3).equals("850")) {
			devolverCodigo = arrayCodigosPais[7];

		} else if (sol.substring(0, 3).equals("890")) {
			devolverCodigo = arrayCodigosPais[8];

		} else {
			devolverCodigo = "Desconocido";
		}
		return devolverCodigo;
	}

	/**
	 * Main que llama a su constructor
	 * 
	 * @param args
	 */
	public static void main(String[] args) {
		new CodigoDeBarras();
	}
}

/**
 * 
 * @author Hijos de Object Excepcion cuando el numero supera los 13 caracteres
 */
@SuppressWarnings("serial")
class NumeroLargoException extends Exception {
	/**
	 * Redefino el metodo
	 */
	public String toString() {
		return "El numero supera el limite establecido.";
	}
}